package chapter12.eg2;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.CharsetUtil;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NettyMessageDecoder extends MessageToMessageDecoder<ByteBuf> {

  private MarshallingDecoder marshallingDecoder;

  public NettyMessageDecoder() throws IOException {
    this.marshallingDecoder = new MarshallingDecoder();
  }

  @Override
  protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
    throws Exception {
    NettyMessage message = new NettyMessage();
    Header header = new Header();
    header.setCrcCode(in.readInt());
    header.setLength(in.readInt());
    header.setSessionID(in.readLong());
    header.setType(in.readByte());
    header.setPriority(in.readByte());

    int size = in.readInt();
    if (size > 0) {
      Map<String, Object> attachement = new HashMap<>();
      int keySize = 0;
      byte[] keyArray = null;
      String key = null;
      for (int i = 0; i < size; i++) {
        keySize = in.readInt();
        keyArray = new byte[keySize];
        in.readBytes(keyArray);
        key = new String(keyArray, CharsetUtil.UTF_8);
        attachement.put(key, marshallingDecoder.decode(in));
      }

      keyArray = null;
      key = null;
      header.setAttachement(attachement);
    }

    if (in.readableBytes() > 4) {
      message.setBody(marshallingDecoder.decode(in));
    }

    message.setHeader(header);
    out.add(message);
  }
}
